package com.mezz.bones.im.logic.interceptor;

import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import com.alibaba.fastjson.JSONObject;
import com.mezz.bones.framework.base.domain.response.Result;
import com.mezz.bones.im.common.domain.dto.ApplicationDto;
import com.mezz.bones.im.common.exception.ImBaseException;
import com.mezz.bones.im.common.result.ImResult;
import com.mezz.bones.im.common.result.ImResultCode;
import com.mezz.bones.im.common.service.IApplicationService;
import com.mezz.bones.im.common.service.IAuthService;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.annotation.Resource;

@Component
public class ImAuthInterceptor implements HandlerInterceptor {

    @Resource
    private IAuthService authService;

    @Resource
    private IApplicationService applicationService;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 如果请求路径包含 "no-auth", 则跳过token验证
        if (request.getRequestURI().contains("/no-auth/")) {
            return true;
        }

        // 获取header中的token
        String token = request.getHeader("token");
        String sign = request.getHeader("sign");

        // 验证token
        try {
            if(StrUtil.isNotBlank(token)){
                //用户端连接是使用token
                authService.validateToken(token);
            }

            if(StrUtil.isNotBlank(sign)){
                //业务端连接是使用sign加签方式
                validateSign(request);
            }

            return true;
        } catch (Exception e) {
            response.setStatus(200);
            response.setCharacterEncoding("utf-8");
            response.getWriter().write(JSONObject.toJSONString(Result.error(ImResultCode.USER_SIGN_ERROR.getCode(),e.getMessage())));
            return false;
        }
    }

    private void validateSign(HttpServletRequest request) {
        String appId = request.getHeader("appId");
        String nonce = request.getHeader("nonce");
        String timestamp = request.getHeader("timestamp");
        String sign = request.getHeader("sign");
        String url = request.getRequestURI();

        if (StrUtil.hasBlank(appId, nonce, timestamp, sign)) {
            throw new ImBaseException(ImResultCode.USER_SIGN_ERROR, "签名参数不完整");
        }

        // 获取应用信息
        ApplicationDto applicationDto = applicationService.getByAppId();
        if (applicationDto == null) {
            throw new ImBaseException(ImResultCode.USER_SIGN_ERROR, StrUtil.format("appId:{}不存在", appId));
        }

        // 生成签名
        String plaintext = StrUtil.concat(true, applicationDto.getAppSecret(),
                appId,
                url,
                nonce,
                timestamp,
                applicationDto.getAppSecret()
        );
        String calculatedSign = SecureUtil.sha256(plaintext);

        // 验证签名
        if (!sign.equals(calculatedSign)) {
            throw new ImBaseException(ImResultCode.USER_SIGN_ERROR, "签名验证失败");
        }

        // 验证时间戳，防止重放攻击（可选，建议添加）
        long requestTime = Long.parseLong(timestamp);
        long currentTime = System.currentTimeMillis();
        if (Math.abs(currentTime - requestTime) > 300000) { // 5分钟有效期
            throw new ImBaseException(ImResultCode.USER_SIGN_ERROR, "请求已过期");
        }
    }
}